import 'package:flutter/material.dart';
import 'package:flutter_demo/pages/page_with_title.dart';
import 'package:flutter_demo/widgets/app_widgets.dart';

class ListPage extends PageWithTitle {
  const ListPage({super.key}) : super("列表(ListView、GridView)");

  @override
  List<Widget> buildContentWidgets(BuildContext context) {
    return const [
      PrimaryTitle("简介"),
      BodyText(
          "列表组件拥有与线性布局一致的子组件排布，区别在于它内容超出列表时可以滚动，而且"
              "在针对存在大量子组件时性能上更有优势，因为它只会挂载当前可视区域内的子组件。"),
      AppSpacer.large,
      _ListExample(),
      AppSpacer.mini,
      UlItem("ListView"),
      BodyText("列表视图，构建一个列表来显示数据"),
      CategoryTitle("常规构造"),
      LabelText("- scrollDirection 列表方向（横向、纵向）"),
      LabelText("- reverse 反转列表布局方向，从结束位置开始布局"),
      LabelText(
          "- controller 列表控制器，主要用于手动控制列表显示位置或监听列表滚动"),
      LabelText(
          "- physics 列表怎么响应用户的滚动手势，这个参数可以设置为不响应用户手势"),
      LabelText(
          "- shrinkWrap 列表主轴方向根据所有条目的高度收缩列表尺寸，这可以用于在列表中"
              "嵌套列表，但同时也变得跟线性布局无异，通常是需要给列表在主轴方向提供一个精确大小，让"
              "他可以在内容超出列表显示区域时通过滚动来浏览，通常这个属性会配合physics设置列表不拦"
              "截用户手势，以避免外部列表的滚动"),
      LabelText(
          "- padding 边距，跟直接包裹Padding组件的区别在于主轴方向的padding是可以跟"
              "随条目滚动的"),
      LabelText(
          "- children 子组件列表，适合只包含少量item的组件使用，推荐在大量数据时使用"
              "builder构造，这样可以在需要时才去构建条目组件，而非一开始全部创建好"),
      NoticeText(
          "列表性能相关的优化属性：默认列表会逐个测量条目高度来实现排布，但这会存在大量"
              "的计算，特别是快速滚动时会有性能压力，为此列表组件提供一部分参数用于快速计算条目位置"),
      LabelText(
          "- prototypeItem 原型条目，很多需求是列表组件都是一致的，只是数据不同，提供"
              "一个原型条目给列表，他会测量一次然后将得到的高度应用于所有item，这样就避免了需要测量"
              "每个item高度才能排布的问题"),
      LabelText(
          "- itemExtent 直接指定条目尺寸，列表直接按照这个尺寸去排布每个item"),
      LabelText(
          "- itemExtentBuilder 提供一个条目尺寸获取的回调，列表需要获取条目尺寸时通"
              "过回调来获取，开发者可以参考当前条目序列、滚动位置、列表宽高等信息决定这个条目的高度"
              "，这种方式适合用于条目具有多种类型的列表使用使用"),
      CategoryTitle("builder构造 ListView.builder"),
      BodyText(
          "适用于大数据量的列表构建，列表组件会根据当前视窗位置通过回调构建要显示的条目组"
              "件，这样就避免了一次性构建大量组件的性能问题"),
      LabelText("- itemCount 告知列表条目数量"),
      LabelText("- itemBuilder 条目构建器，通过回调在需要显示时才构建item"),
      CategoryTitle("separated构造 ListView.separated"),
      BodyText(
          "在builder构建的基础上，此构造方式让列表组件在条目之间可以插入间隔组件，它会通"
              "过回调来构造间隔组件"),
      LabelText("- itemCount 告知列表条目数量"),
      LabelText("- itemBuilder 条目构建器，通过回调在需要显示时才构建item"),
      LabelText(
          "- separatorBuilder 间隔构建器，通过回调在目标的item下方创建间隔组件"),
      CategoryTitle("custom构造 ListView.custom"),
      BodyText("没觉得比上方的构建方式有什么优点。。。"),
      AppSpacer.large,
      _GridExample(),
      AppSpacer.mini,
      UlItem("GridView"),
      BodyText(
          "网格视图，可以视为支持多列的列表视图，所以最主要的是掌握如何划分多列，其它参数"
              "于列表视图一致这里累述了"),
      AppSpacer.large,
      CategoryTitle("常规构造"),
      BodyText(
          "很少人直接用这个，一般直接使用count构造或extent构造可以节省一些代码。。。"),
      LabelText(
          "-  gridDelegate 网格代理，用于配置网格视图的列如何划分，Flutter实现了以"
              "下两种方案"),
      LabelText(
          "    -  SliverGridDelegateWithFixedCrossAxisCount 固定交叉轴上的"
              "item数量，参考count构造"),
      LabelText(
          "    -  SliverGridDelegateWithMaxCrossAxisExtent 根据设置的item在"
              "交叉轴上的最大空间占用，网格视图结合自身在交叉轴上的实际尺寸自动计算交叉轴上可容纳"
              "item数量，参考extent构造"),
      AppSpacer.large,
      CategoryTitle("count构造，GridView.count"),
      BodyText(
          "就是应用SliverGridDelegateWithFixedCrossAxisCount代理的构造，将其需要"
              "的参数暴露到此构造器中方便快速实现固定列数的网格视图"),
      LabelText("-  crossAxisCount 指定交叉轴上的item数量"),
      LabelText("-  mainAxisSpacing 主轴上item间距"),
      LabelText("-  crossAxisSpacing 交叉轴上item间距"),
      LabelText(
          "-  childAspectRatio 子组件宽高比，默认1:1，自适应item高度会有性能问题，"
              "网格视图不允许这么做"),
      AppSpacer.large,
      CategoryTitle("extent构造，GridView.extent"),
      BodyText(
          "就是应用SliverGridDelegateWithMaxCrossAxisExtent代理的构造，将其需要"
              "的参数暴露到此构造器中方便快速实现根据容器宽度和指定的最大item宽度来动态计算列数"),
      LabelText(
          "-  maxCrossAxisExtent item最大宽度，会根据容器宽度来计算可容纳的item数"
              "量"),
      LabelText("-  mainAxisSpacing 主轴上item间距"),
      LabelText("-  crossAxisSpacing 交叉轴上item间距"),
      LabelText(
          "-  childAspectRatio 子组件宽高比，默认1:1，自适应item高度会有性能问题，"
              "网格视图不允许这么做"),

      AppSpacer.large,
      CategoryTitle("builder构造，GridView.builder"),
      BodyText("跟列表视图的builder构造一样，需要开发者自己设置itemCount，然后由网格视图在"
              "item可见时通过itemBuilder构建item组件"),
      AppSpacer.large,
      CategoryTitle("custom构造，自定义构造，基本用不到"),
    ];
  }
}

class _ListExample extends StatelessWidget {
  const _ListExample();

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const BodyText("横向列表"),
        SizedBox(
          height: 40,
          child: ListView(
            scrollDirection: Axis.horizontal,
            children: List.generate(
              10,
                  (index) {
                return Padding(
                  padding: const EdgeInsetsDirectional.only(end: 5),
                  child: Text(
                    "item$index",
                    style: TextStyle(
                        backgroundColor:
                        Theme
                            .of(context)
                            .colorScheme
                            .surfaceContainer),
                  ),
                );
              },
            ),
          ),
        ),
        AppSpacer.mini,
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              child: Column(
                children: [
                  const BodyText("在条目显示时构建组件"),
                  ListView.builder(
                    shrinkWrap: true,
                    itemCount: 10,
                    itemExtent: 25,
                    itemBuilder: (context, index) {
                      return Text(
                        "item$index",
                        style: TextStyle(
                            backgroundColor:
                            Theme
                                .of(context)
                                .colorScheme
                                .surfaceContainer),
                      );
                    },
                  ),
                ],
              ),
            ),
            Expanded(
              child: Column(
                children: [
                  const BodyText("条目间隔"),
                  ListView.separated(
                    shrinkWrap: true,
                    itemCount: 10,
                    itemBuilder: (context, index) {
                      return Text(
                        "item$index",
                        style: TextStyle(
                            backgroundColor:
                            Theme
                                .of(context)
                                .colorScheme
                                .surfaceContainer),
                      );
                    },
                    separatorBuilder: (context, index) {
                      return Container(
                        color: Theme
                            .of(context)
                            .colorScheme
                            .outline,
                        height: 1,
                      );
                    },
                  ),
                ],
              ),
            ),
          ],
        ),
      ],
    );
  }
}

class _GridExample extends StatelessWidget {
  const _GridExample();

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const BodyText("固定交叉轴上item数量"),
        GridView(
          physics: const NeverScrollableScrollPhysics(),
          shrinkWrap: true,
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 4,
            mainAxisSpacing: 5,
            crossAxisSpacing: 5,
            childAspectRatio: 16 / 9,
          ),
          children: List.generate(
            10,
                (index) {
              return Container(
                alignment: Alignment.center,
                color: Theme
                    .of(context)
                    .colorScheme
                    .surfaceContainer,
                child: Text("item$index"),
              );
            },
          ),
        ),
        AppSpacer.mini,
        const BodyText(
            "根据item在交叉轴上的尺寸于列表交叉轴尺寸，自动计算可以在交叉轴容纳多少个item"),
        SizedBox(
          height: 100,
          child: GridView.builder(
            scrollDirection: Axis.horizontal,
            gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
              maxCrossAxisExtent: 40,
              mainAxisSpacing: 5,
              crossAxisSpacing: 5,
              childAspectRatio: 9 / 16,
            ),
            itemCount: 1000,
            itemBuilder: (context, index) {
              return Container(
                alignment: Alignment.center,
                color: Theme
                    .of(context)
                    .colorScheme
                    .surfaceContainer,
                child: Text("item$index"),
              );
            },
          ),
        )
      ],
    );
  }
}
